# -*- encoding: utf8 -*-

from datetime import datetime
from django import forms
from django.contrib.admin import widgets
from reps.interns.helpers import send_mail, generate_password
from reps.interns.models import *

class TestForm(forms.Form):
    text = forms.CharField()
    int = forms.IntegerField()


class StudentForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='Imię')
    last_name = forms.CharField(max_length=30, label='Nazwisko')
    email = forms.EmailField(label='Email')
    book_no = forms.CharField(max_length=20, label='Nr indeksu')
    specialization = \
        forms.ChoiceField(choices=tuple((i.id, i.full_name)
                                        for i in Specialization.objects.all()),
                          label='Kierunek')
    year_of_study = forms.IntegerField(label='Rok studiów')

    def __init__(self, data=None, student=None, initial={}):
        if student:
            user = student.profile.user
            temp = initial
            initial = {'first_name': user.first_name,
                       'last_name': user.last_name,
                       'email': user.email,
                       'book_no': student.book_no,
                       'specialization': student.specialization.id,
                       'year_of_study': student.year_of_study,
                       }
            initial.update(temp)
            self.base_fields['email'].required = student.is_registered()
        else:
            user = None
        super(StudentForm, self).__init__(data=data, initial=initial)
        self.student = student
        self.user = user

    def save(self):
        user = self.user
        student = self.student
        data = self.cleaned_data
        user.first_name = data['first_name']
        user.last_name = data['last_name']
        user.email = data['email']
        student.book_no = data['book_no']
        student.specialization = Specialization.objects.get(id=data['specialization'])
        student.year_of_study = data['year_of_study']
        user.save()
        student.save()
        return student


class NewStudentForm(forms.Form):
    first_name = forms.CharField(max_length=30, label='Imię')
    last_name = forms.CharField(max_length=30, label='Nazwisko')
    book_no = forms.CharField(max_length=20, label='Nr indeksu')
    specialization = \
        forms.ChoiceField(choices=tuple((i.id, i.full_name)
                                        for i in Specialization.objects.all()),
                          label='Kierunek')
    year_of_study = forms.IntegerField(label='Rok studiów')

    def __init__(self, data=None, spec_id=None, initial={}):
        if spec_id:
            temp = initial
            initial = {'specialization': spec_id}
            initial.update(temp)
        super(NewStudentForm, self).__init__(data=data, initial=initial)

    def save(self):
        data = self.cleaned_data
        specialization = Specialization.objects.get(id=int(data['specialization']))
        student = Student.new(data['first_name'],
                              data['last_name'],
                              data['book_no'],
                              specialization,
                              year_of_study=int(data['year_of_study']))
        self.student = student
        return student


class ResetPasswordForm(forms.Form):
    book_no = forms.CharField(max_length=20, label='Nr indeksu')

    def save(self):
        try:
            book_no = self.cleaned_data['book_no']
            student = Student.objects.get(book_no=book_no)
            user = student.user()
            password = generate_password()
            user.set_password(password)
            user.save()
            send_mail(u'RePS: przywrócenie hasła', u'Wygenerowano nowe hasło.\nDane do zalogowania:\n\tNazwa użytkownika: %s\n\tHasło: %s\n' % (user.username, password), user.email)
        except: # ignore for security reasons
            pass


class RegisterForm(forms.Form):
    student = forms.ChoiceField(label='Student')
    book_no = forms.CharField(max_length=20, label='Nr indeksu')
    username = forms.CharField(max_length=30, label=u'Nazwa użytkownika')
    email = forms.EmailField(label='Email')
 
    def __init__(self, data=None, spec=None, initial={}):
        if spec:
            self.fill_choices(spec)
        super(RegisterForm, self).__init__(data=data, initial=initial)
   
    def fill_choices(self, spec):
        self.base_fields['student'].choices = \
                [(i.id, unicode(i)) for i in spec.unregistered_students()]

    def clean_username(self):
        username = self.cleaned_data['username'].lower()
        if not username.isalnum() or not username[0].isalpha():
            raise forms.ValidationError(u'Nazwa użytkownika musi być alfanumeryczna i zaczynać się literą')
        if User.objects.filter(username=username):
            raise forms.ValidationError(u'Login "%s" jest już zajęty' % username)
        else:
            return username

    def clean_book_no(self):
        student = Student.objects.get(id=self.cleaned_data['student'])
        if student.book_no != self.cleaned_data['book_no']:
            raise forms.ValidationError(u'Niepoprawny numer indeksu: %s' % self.cleaned_data['book_no'])
        else:
            return self.cleaned_data['book_no']

    def save(self):
        data = self.cleaned_data
        student = Student.objects.get(id=self.cleaned_data['student'])
        user = student.user()
        password = generate_password()
        user.set_password(password)
        user.email = data['email']
        user.username = data['username']
        user.is_active = True
        send_mail('RePS: rejestracja', u'Dziękujemy za rejestrację w systemie RePS.\nDane do zalogowania:\n\tNazwa użytkownika: %s\n\tHasło: %s\n' % (user.username, password), user.email)
        user.save()


class ChangeEmailForm(forms.Form):
    email = forms.EmailField()


class ChangePasswordForm(forms.Form):
    old_password = forms.CharField(widget=forms.PasswordInput, label=u'Stare hasło')
    password1 = forms.CharField(widget=forms.PasswordInput, label=u'Nowe hasło')
    password2 = forms.CharField(widget=forms.PasswordInput, label=u'Powtórz nowe hasło')

    def clean_password2(self):
        password1 = self.cleaned_data['password1']
        password2 = self.cleaned_data['password2']
        if password1 != password2:
            raise forms.ValidationError(u'Hasła muszą się zgadzać')
        return password2


class BranchForm(forms.ModelForm):
    main_branch = forms.ModelChoiceField(label='Siedziba główna',
                                         required=False,
                                         queryset=Branch.main_branches())

    def clean_main_branch(self):
        mb = self.cleaned_data['main_branch']
        instance = self.instance
        if(instance.id != None and instance.main_branch == None
           and mb and instance.branch_set.all()):
                raise forms.ValidationError(u'Nie można zmienić siedziby głównej w filię, jeżeli posiada ona już inne filie')
        return mb

    class Meta:
        model = Branch
        exclude = ['created_by']


class TrainingForm(forms.ModelForm):
    new_insurance = forms.CharField(label='Nowy ubezpieczyciel', required=False)

    def __init__(self, data=None, initial=None, instance=None):
        if instance:
            spec = instance.student.specialization
            training_dates = Training_Date.objects.filter(specialization=spec)
            self.base_fields['training_date'].queryset = training_dates
            self.base_fields.keyOrder = ['branch', 'training_date', 'street',
                                         'postal_code', 'city', 'is_foreigner',
                                         'hostel', 'payable', 'insurance_company',
                                         'new_insurance', 'insurance_number',
                                         'is_working', 'socrates']
        super(TrainingForm, self).__init__(data=data,
                                           initial=initial,
                                           instance=instance)

    def clean(self):
        data = self.cleaned_data
        company = data['insurance_company']
        new_company = data['new_insurance']
        number = data['insurance_number']
        if not company:
            if new_company:
                if not number:
                    raise forms.ValidationError(u'Należy wprowadzić ubezpieczyciela (wybrać z listy ALBO zostawić "---------" i wpisać nowego) ORAZ podać numer ubezpieczenia. <br><b>Aby wprowadzić domyślne ubezpieczenie</b>, należy pozostawić "---------" na liście rozwijanej, puste pole nowego ubezpieczyciela i puste pole numeru.')
                company = Training_Insurance(name=new_company)
                company.save()
            else:
                if number:
                    raise forms.ValidationError(u'Należy wprowadzić ubezpieczyciela (wybrać z listy ALBO zostawić "---------" i wpisać nowego) ORAZ podać numer ubezpieczenia. <br><b>Aby wprowadzić domyślne ubezpieczenie</b>, należy pozostawić "---------" na liście rozwijanej, puste pole nowego ubezpieczyciela i puste pole numeru.')
                company = Setting.default_insurance_company()
                number = Setting.default_insurance()
        else:
            if new_company:
                raise forms.ValidationError(u'Wybierz ubezpieczyciela z listy ALBO na liście wybierz "---------" i wpisz nowego ubezpieczyciela.')
            if not number:
                raise forms.ValidationError(u'Należy wybrać ubezpieczyciela (wybrać z listy ALBO zostawić "---------" i wpisać nowego) ORAZ podać numer ubezpieczenia. <br><b>Aby wprowadzić domyślne ubezpieczenie</b>, należy pozostawić "---------" na liście rozwijanej, puste pole nowego ubezpieczyciela i puste pole numeru.')
            
        data['insurance_company'] = company
        data['insurance_number'] = number
        return data

    class Meta:
        model = Training
        exclude = ['student', 'contract_date', 'pass_date', 'remarks', 'locked',
                   'dont_print_contract', 'mark', 'is_archival']


class MarkTrainingFrom(forms.Form):
    MARK_CHOICES = (('-', 'zal'), ) + tuple((m, m) for m in Training.MARKS)

    mark = forms.ChoiceField(choices=MARK_CHOICES, label='Ocena')
    pass_date = forms.DateField(required=False, label='Data zaliczenia', widget=widgets.AdminDateWidget())

    def clean_mark(self):
        mark = self.cleaned_data['mark']
        if mark == '-':
            return None
        return mark


class UploadStudentsFileForm(forms.Form):
    specialization = forms.ChoiceField(label='Kierunek')
    codepage = forms.ChoiceField(label='Kodowanie pliku')
    file = forms.FileField(label='Plik')

    def __init__(self, data=None, files=None, initial={}, choices=()):
        super(UploadStudentsFileForm, self).__init__(data=data,
                                                     files=files,
                                                     initial=initial)
        self.fields['specialization'].choices = choices
        self.fields['codepage'].choices = (("windows-1250","Windows-1250"), ("utf8","Utf-8"), ("iso-8859-2","Iso-8859-2"), ("ascii","ASCII"))


class ReportForm(forms.Form):
    specialization = forms.ChoiceField(label='Kierunek')
    startdate = forms.ChoiceField(label='Początek')
    enddate = forms.ChoiceField(label='Koniec')

    def __init__(self, data=None, initial={}, specchoices=(), startchoices=(), endchoices=()):
        super(ReportForm, self).__init__(data=data,
                                         initial=initial)
        self.fields['specialization'].choices = specchoices
        self.fields['startdate'].choices = startchoices
        self.fields['enddate'].choices = endchoices
        

class TrainingDateForm(forms.ModelForm):
    def __init__(self, *args, **kwargs):
        super(TrainingDateForm, self).__init__(*args, **kwargs)
        self.fields['start_date'].widget = widgets.AdminDateWidget()
        self.fields['end_date'].widget = widgets.AdminDateWidget()

    class Meta:
        model = Training_Date
        exclude = ['specialization']


class TrainingDateGenerationForm(forms.Form):
    DAYS = [
        ('mon', 'poniedziałek'),
        ('tue', 'wtorek'),
        ('wed', 'środę'),
        ('thu', 'czwartek'),
        ('fri', 'piątek'),
        ('sat', 'sobotę'),
        ('sun', 'niedzielę'),
    ]

    first_day = forms.DateField(label=u'Pierwszy możliwy dzień praktyki', widget=widgets.AdminDateWidget())
    last_day = forms.DateField(label=u'Ostatni możliwy dzień praktyki', widget=widgets.AdminDateWidget())
    length = forms.IntegerField(label=u'Długość praktyki (w dniach)')

    def __init__(self, data=None):
        for field_name, label_part in self.DAYS:
            self.base_fields[field_name] =\
                forms.BooleanField(label=label_part, required=False)
        super(TrainingDateGenerationForm, self).__init__(data=data)

    def clean_last_day(self):
        data = self.cleaned_data
        if data['first_day'] > data['last_day']:
            raise forms.ValidationError('Ostatni dzień praktyki powinien być po pierwszym.')
        return data['last_day']

    def clean(self):
        data = self.cleaned_data
        count = 0
        for field_name, label_part in self.DAYS:
            if data[field_name]:
                count += 1
        if count == 0:
            raise forms.ValidationError('Wybierz co najmniej jeden dzień.')
        return data

    def generate_dates(self, specializations):
        first_day = self.cleaned_data['first_day']
        last_day = self.cleaned_data['last_day']
        length = self.cleaned_data['length']
        allowed_days = set()
        for i, day in zip(xrange(7), self.DAYS):
            if self.cleaned_data[day[0]]:
                allowed_days.add(i)
        results = []
        for spec in specializations:
            for offset in xrange(last_day.toordinal() - first_day.toordinal() - length):
                start = datetime.fromordinal(first_day.toordinal() + offset)
                end = datetime.fromordinal(first_day.toordinal() + offset + length)
                if start.weekday() in allowed_days:
                    results.append(Training_Date(specialization=spec,
                                                 start_date=start,
                                                 end_date=end))
        return results


class SettingsForm(forms.Form):
    default_insurance_company = \
        forms.ModelChoiceField(queryset=Training_Insurance.objects.all(),
                               label=u'Domyślny ubezpieczyciel')
    default_insurance = forms.CharField(label=u'Numer domyślnej polisy')

